
#include <iostream>
#include <crafter.h>

/* Collapse namespaces */
using namespace std;
using namespace Crafter;

void error(const char *msg)
{
    std::cout<<"error"<<std::endl;
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[]) {
        
         /* Set the interface */
        string iface = "wlan0";
        
        int rawsock;

        if((rawsock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)))== -1)
                exit(1);

        struct sockaddr_ll sll;
        struct ifreq ifr;

        memset(&sll,0,sizeof(sll));
        memset(&ifr,0,sizeof(ifr));

        /* First Get the Interface Index  */
        strncpy((char *)ifr.ifr_name, iface.c_str(), IFNAMSIZ);
        if((ioctl(rawsock, SIOCGIFINDEX, &ifr)) == -1)
        {
                perror("Getting Interface index");
                exit(1);
        }

        /* Bind our raw socket to this interface */
        sll.sll_family = AF_PACKET;
        sll.sll_ifindex = ifr.ifr_ifindex;
        sll.sll_protocol = htons(ETH_P_ALL);


        if((bind(rawsock, (struct sockaddr *)&sll, sizeof(sll)))== -1)
        {
                perror("Binding raw socket to interface");
                exit(1);
        }
     
        char buffer[255];
        bzero((char *) &buffer, sizeof(buffer));
        strcpy(buffer,"Arbitraryr111111111111aryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloadArbitraryPayloa");
        
        /* Get the IP address associated to the interface */
        string MyIP = GetMyIP(iface);
        cout << "[@] My IP address is  : " << MyIP  << endl;

        /* Get the MAC Address associated to the interface */
        string MyMAC = GetMyMAC(iface);

        Ethernet ether_header;

        ether_header.SetSourceMAC(MyMAC);
        ether_header.SetDestinationMAC("c8:3a:35:cf:1d:b0");
        
        /* Create an IP header */
        IP ip_header;
        /* Set the Source and Destination IP address */
        ip_header.SetSourceIP(argv[1]);
        ip_header.SetDestinationIP(argv[2]);

        /* Create an TCP - SYN header */
        TCP tcp_header;
        tcp_header.SetSrcPort(unsigned(atoi(argv[3])));
        tcp_header.SetDstPort(unsigned (atoi(argv[4])));
        tcp_header.SetSeqNumber(unsigned (atoi(argv[5])));
        tcp_header.SetAckNumber(unsigned (atoi(argv[6])));
        tcp_header.SetWindowsSize(114);
        tcp_header.SetFlags(0x18);  
        /* Create a packets */
        
       TCPConnection tcp_connection(argv[1],argv[2],(unsigned(atoi(argv[3]))),(unsigned(atoi(argv[4]))),iface,TCPConnection::ESTABLISHED);
       
	/* Time stamp option */
	TCPOptionTimestamp tstamp;
	tstamp.SetKind(8);
        tstamp.SetValue(1093475);
        tstamp.SetLength(10);
        tstamp.SetEchoReply(1390293);

        RawLayer raw_header;
	raw_header.SetPayload(buffer);
        
        Packet tcp_packet = ether_header / ip_header / tcp_header /
					TCPOption::NOP /  
					TCPOption::NOP /
                                        tstamp /
                                        raw_header;

        cout << endl << "[@] Print before sending: " << endl;
        tcp_packet.Print();
        /* Write the packet on the wire */
        tcp_packet.Send(iface);
        //tcp_connection.Sync();
        //tcp_connection.Send(buffer);

        cout << endl << "[@] Print after sending: " << endl;
        tcp_packet.Print();
        close(rawsock);

        return 0;
}